<?php

date_default_timezone_set('Europe/Vilnius');
include './FourInALinePlayer.php';

class PlayerOld extends FourInALinePlayer {

    public $move = 0;
    public $gameNumber = 10;
    private $grid;

    /* Makes one move on the given $grid */

    public function makeMove($grid, $column, $playerKind) {
        for ($i = 0; $i < $this->height; $i++) {
            if ($grid[$column][$i] === null) {
                $grid[$column][$i] = $playerKind;
            }
        }
    }

    private function isOneStepToWin(array $grid) {
        $value = $this->checkForThreeOfFour($grid, $this->currentPlayer);
        return $value;
    }

    public function isOneStepToLose(array $grid) {
        $enemy = 3 - $this->currentPlayer;
        return $this->checkForThreeOfFour($grid, $enemy);
    }

    /* Chack if my choice will cause situation where enemy is one step to win */

    public function willMyChoiceCauseOneStepToLose($column) {
        $futureGrid = array($this->grid);
        $this->makeMove($futureGrid, $column, $this->currentPlayer);
        $futureVal = $this->isOneStepToLose($futureGrid);
        if ($futureVal !== -1)
            return true;
        return false;
    }

    public function getMove(array $grid) {
        $this->grid = $grid;
        $this->whereAreWe();
        $column = -1;
        $column = $this->isOneStepToWin($grid);
        if ($column === -1)
            $column = $this->isOneStepToLose($grid);
        if ($column === -1)
            $column = $this->checkForTwofFive($this->currentPlayer);
        if ($column === -1)
            $column = $this->checkForTwofFive(3 - $this->currentPlayer);
        if ($column === -1) {
            while (true) {
                $column = mt_rand(0, $this->width - 1);
                if (in_array(null, $this->grid[$column], true)) {
                    if (!$this->willMyChoiceCauseOneStepToLose($column)) {
                        break;
                    }
                }
            }
        }
        return $column;
    }

    public function getName() {
        return "'Old' guy";
    }

    public function checkForThreeOfFour(array $grid, $playerKind) {
        /* checking for vertical win situation */
        for ($i = 0; $i < $this->width; $i++) {
            for ($j = 0; $j < $this->height - 3; $j++) {
                if (array_sum(array($grid[$i][$j], $grid[$i][$j + 1], $grid[$i][$j + 2])) === 3 * $playerKind &&
                        $grid[$i][$j + 3] === null && $grid[$i][$j + 2] !== null) {
                    $value = $i;
                    if ($this->gameNumber === 1)
                        echo " manau turetu buti vertikalus col={$i} su player={$playerKind}\n";
                    return $value;
                }
            }
        }
        /* checking for horizontal win situation */
        for ($j = 0; $j < $this->height; $j++) {
            for ($i = 0; $i < $this->width - 3; $i++) {
                $var = array($grid[$i][$j], $grid[$i + 1][$j], $grid[$i + 2][$j], $grid[$i + 3][$j]);
                if (in_array($playerKind, $var) && in_array(null, $var) && !in_array(3 - $playerKind, $var) &&
                        array_sum($var) === 3 * $playerKind) {
                    $value = $this->findNull($var);
                    if (isset($grid[$i + $value][$j - 1]) || $j === 0) {
                        if ($this->gameNumber === 1)
                            echo " manau turetu buti horizontalus col={($i + $value)} su player={$playerKind}\n";
                        return ($i + $value);
                    }
                }
            }
        }
        /* checking for diagonal win situation */
        for ($i = 0; $i < $this->width; $i++) {
            for ($j = 0; $j < $this->height - 3; $j++) {
                /* check to the right */
                if ($i < $this->width - 3) {
                    $var = array($grid[$i][$j], $grid[$i + 1][$j + 1], $grid[$i + 2][$j + 2], $grid[$i + 3][$j + 3]);
                    if (in_array($playerKind, $var) && in_array(null, $var) && !in_array(3 - $playerKind, $var) &&
                            array_sum($var) === 3 * $playerKind) {
                        $value = $this->findNull($var);
                        if (isset($grid[$i + $value][$j + $value - 1]) || ($j + $value) === 0) {
                            if ($this->gameNumber === 1)
                                echo " manau turetu buti dagonalus i desine col={($i + $value)} su player={$playerKind}\n";
                            return ($i + $value);
                        }
                    }
                }
                /* check to the left */
                if ($i > 2) {
                    $var = array($grid[$i][$j], $grid[$i - 1][$j + 1], $grid[$i - 2][$j + 2], $grid[$i - 3][$j + 3]);
                    if (in_array($playerKind, $var) && in_array(null, $var) && !in_array(3 - $playerKind, $var) &&
                            array_sum($var) === 3 * $playerKind) {
                        $value = $this->findNull($var);
                        if (isset($grid[$i - $value][$j + $value - 1]) || ($j + $value) === 0) {
                            if ($this->gameNumber === 1)
                                echo " manau turetu buti dagonalus i kaire col={($i - $value)} su player={$playerKind}\n";
                            return ($i - $value);
                        }
                    }
                }
            }
        }
        return -1;
    }

    /* check for situartion where you could win in two turns */

    public function checkForTwofFive($playerKind) {
        /* checking for only horizontal win situation */
        for ($j = 0; $j < $this->height; $j++) {
            for ($i = 0; $i < $this->width - 4; $i++) {
                if ($this->grid[$i][$j] !== null || $this->grid[$i + 4][$j] !== null)
                    continue;
                $var = array($this->grid[$i + 1][$j], $this->grid[$i + 2][$j], $this->grid[$i + 3][$j]);
                if (in_array($playerKind, $var) && in_array(null, $var) && !in_array(3 - $playerKind, $var) &&
                        array_sum($var) === 2 * $playerKind) {
                    $value = $this->findNull($var);
                    $value = $value + $i + 1;
                    if (isset($this->grid[$value][$j - 1]) || $j === 0) {
                        if ($this->gameNumber === 1)
                            echo " manau turetu buti 2of5 eiluteje=$j ir  col={($value)} su player={$playerKind}\n";
                        return ($value);
                    }
                }
            }
        }
        /* TODO add cheking diagonal 2of5 */
        return -1;
    }

    protected function findNull(array $list) {
        for ($i = 0; $i < count($list); $i++)
            if ($list[$i] === null)
                return $i;
        return -1;
    }

    protected function isColumbFree(array $grid, $column) {
        if (in_array(null, $grid[$column], true))
            return true;
        return false;
    }

    protected function whereAreWe() {
        if ($this->isItNewGame()) {
            $this->gameNumber++;
            $this->move = 0;
        }
        else
            $this->move++;
    }

    public function isItNewGame() {
        $firstLineSum = 0;
        for ($i = 0; $i < $this->width; $i++)
            $firstLineSum = $firstLineSum + $this->grid[$i][0];
        if ($firstLineSum < 3 && $this->move > 4)
            return true;
        return false;
    }

    /* gets random move. at the begining of game tries to move near center */

    public function getRandom($untill = -1) {
        // imported from newer player
        if ($untill === -1)
            $untill = $this->width;
        if ($untill - $this->gameNumber > 0) {
            $delta = intval($this->width * (0.1 + 0.2*($untill - $this->gameNumber)/$untill));
            $start = 0 + $delta;
            $end = $this->width - 1 - $delta;
        } else {
            $start = 0;
            $end = $this->width - 1;
        }
        while (true) {
            $column = mt_rand($start, $end);
            if (in_array(null, $this->grid[$column], true)) {
                if (!$this->willMyChoiceCauseOneStepToLose($column)) {
                    break;
                }
            }
        }
        return $column;
    }

    /* for unit tests */
    public function setGrid($grid) {
        $this->grid = $grid;
    }
    public function setGameNumber($gameNumber) {
        $this->gameNumber = $gameNumber;
    }

}
